﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Dycox.Validation;

namespace Dycox.Windows.Forms
{
    [
    ProvideProperty("Enabled", typeof(DataGridView)),
    Description("Provides DataGridView automatic validation ability based on the Dycox.Validation compoentns."),
    ]
    public class DataGridViewValidationProvider : Component, IExtenderProvider
    {
        public DataGridViewValidationProvider()
        {
            _list = new HashSet<DataGridView>();
        }

        public DataGridViewValidationProvider(IContainer container)
            : this()
        {
            if (container == null)
                throw new ArgumentNullException("container");

        }

        HashSet<DataGridView> _list;

        public bool CanExtend(object extendee)
        {
            return extendee is DataGridView;
        }

        [DefaultValue(false)]
        public bool GetEnabled(DataGridView dgv)
        {
            if (dgv == null)
                throw new ArgumentNullException("dgv");

            return _list.Contains(dgv);
        }

        public void SetEnabled(DataGridView dgv, bool enabled)
        {
            if (dgv == null)
                throw new ArgumentNullException("dgv");

            if (enabled)
            {
                if (!_list.Contains(dgv))
                {
                    _list.Add(dgv);
                    WireEvents(dgv);
                }
            }
            else
            {
                _list.Remove(dgv);
                UnwireEvents(dgv);
            }
        }

        private void WireEvents(DataGridView dgv)
        {
            UnwireEvents(dgv);

            dgv.CellValueChanged += DataGridViewCellValueChanged;
        }

        private void UnwireEvents(DataGridView dgv)
        {
            dgv.CellValueChanged -= DataGridViewCellValueChanged;
        }

        void DataGridViewCellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                DataGridView dgv = ((DataGridView)sender);
                DataGridViewRow row = dgv.Rows[e.RowIndex];
                //DataGridViewColumn col = dgv.Columns[e.ColumnIndex];

                if (!row.IsNewRow)
                {
                    var msgSet = ValidationManager.Validate(row.DataBoundItem, false);
                    var lookup = msgSet
                        .Where(o => o.Kind == ComponentModel.MessageKind.Error)
                        .Cast<ValidationMessageEntry>()
                        .ToLookup(o => o.MemberPath);

                    foreach (DataGridViewColumn col in dgv.Columns)
                    {
                        string name = col.DataPropertyName;
                        if (name != null)
                        {
                            var list = lookup[name];
                            var cell = row.Cells[col.Index];
                            if (list.Count() > 0)
                            {
                                cell.ErrorText = string.Join("\n", list.Select(o => o.Text));
                            }
                            else
                                cell.ErrorText = string.Empty;


                        }
                    }

                }
            }
            
        }
        #region Design time support

        public override ISite Site
        {
            get
            {
                return base.Site;
            }
            set
            {
                base.Site = value;
                if (value != null)
                {
                    IComponentChangeService ccsvc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
                    if (ccsvc != null)
                    {
                        ccsvc.ComponentAdded += ccsvc_ComponentAdded;
                        ccsvc.ComponentRemoved += ccsvc_ComponentRemoved;

                        IReferenceService refsvc = (IReferenceService)GetService(typeof(IReferenceService));
                        if (refsvc != null)
                        {
                            foreach (DataGridView dgv in refsvc.GetReferences(typeof(DataGridView)))
                                this.SetEnabled(dgv, true);
                        }

                    }

                }
            }
        }

        void ccsvc_ComponentRemoved(object sender, ComponentEventArgs e)
        {
            if (e.Component is DataGridView)
                this.SetEnabled((DataGridView)e.Component, false);
        }

        void ccsvc_ComponentAdded(object sender, ComponentEventArgs e)
        {
            if (e.Component is DataGridView)
                this.SetEnabled((DataGridView)e.Component, true);
        }

        #endregion
    }
}
